from turtle_nano import Turtle
from machine import SPI, Pin, I2C
import st7789, ds1307, icm20948, utime, math

# 1. 初始化显示屏（只初始化一次）
spi = SPI(0, baudrate=40000000, polarity=1, phase=0, bits=8, endia=0, sck=Pin(6), mosi=Pin(8))
# 初始化ST7789显示屏
display = st7789.ST7789(spi, 240, 240, reset=Pin(11, func=Pin.GPIO, dir=Pin.OUT), dc=Pin(7, func=Pin.GPIO, dir=Pin.OUT))
display.init()
pic = Turtle(display, 120, 120, st7789.color565(255, 255, 255))


# 2. 开始页面绘制函数
def show_start_screen():
    display.fill(st7789.color565(30, 30, 30))
    display.draw_string(40, 90, "Pedometer", size=3, color=st7789.color565(0, 240, 245))
    display.draw_string(20, 130, "Press Key to start", size=2, color=st7789.color565(0, 240, 245))
    display.fill_circle(120, 173, 20, st7789.color565(0, 240, 245))
    display.draw_string(115, 170, "OK", size=2, color=st7789.color565(255, 255, 255))


# 3. 结束页面绘制函数
def show_end_screen(total_steps, total_time, avg_pace):
    display.fill(st7789.color565(30, 30, 30))
    # 显示总步数
    display.draw_string(40, 70, "Total Steps:", size=2, color=st7789.color565(255, 255, 255))
    display.draw_string(180, 70, str(total_steps), size=2, color=st7789.color565(255, 255, 255))

    # 显示运动时间
    hours = total_time // 3600
    minutes = (total_time % 3600) // 60
    seconds = total_time % 60
    time_str = "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)
    display.draw_string(40, 100, "Time:", size=2, color=st7789.color565(255, 255, 255))
    display.draw_string(100, 100, time_str, size=2, color=st7789.color565(255, 255, 255))

    # 显示平均配速
    if avg_pace > 0:
        pace_min = int(avg_pace)
        pace_sec = int((avg_pace - pace_min) * 60)
        pace_str = "{}:{:02d}".format(pace_min, pace_sec)
    else:
        pace_str = "--:--"
    display.draw_string(40, 130, "Avg Pace:", size=2, color=st7789.color565(255, 255, 255))
    display.draw_string(140, 130, pace_str, size=2, color=st7789.color565(255, 255, 255))
    display.draw_string(180, 130, "min/km", size=2, color=st7789.color565(255, 255, 255))


# 4. 按键等待（IRQ 方式）
key_pressed = False


def key_irq(_):
    global key_pressed
    key_pressed = True


key_pin = Pin(13)
key_pin.init(Pin.IN)
key_pin.pull(Pin.PULL_DOWN)
key_pin.irq(trigger=Pin.IRQ_FALLING, handler=key_irq)

# 5. 显示开始页并阻塞等待
show_start_screen()
while not key_pressed:
    utime.sleep_ms(50)

# 6. 进入主程序前把屏幕清掉，防止花屏
display.fill(0)

# ================== 下面是你原来的所有代码 ==================
# 绘制界面元素
color = st7789.color565(254, 98, 31)
pic.penup()
pic.goto(-120, -80)
pic.pendown()

# 绘制标题栏背景
pic.pencolor(st7789.color565(255, 105, 180))
pic.pensize(2)
pic.fillcolor(st7789.color565(255, 105, 180))
pic.begin_fill()
pic.forward(238)
pic.right(90)
pic.forward(40)
pic.right(90)
pic.forward(238)
pic.right(90)
pic.forward(40)
pic.end_fill()
pic.pencolor(color)

display.fill_rect(200, 230, 8, 10, st7789.color565(173, 135, 107))

'''绘制圣诞树（多层三角形）'''
# 第一层三角形（底部）
pic.penup()
pic.goto(64, 109)
pic.pendown()
pic.fillcolor(color)
pic.begin_fill()
pic.goto(104, 109)
pic.goto(84, 99)
pic.goto(64, 109)
pic.end_fill()

# 第二层三角形
pic.penup()
pic.goto(68, 99)
pic.pendown()
pic.fillcolor(color)
pic.begin_fill()
pic.goto(100, 99)
pic.goto(84, 88)
pic.goto(68, 99)
pic.end_fill()

# 第三层三角形
pic.penup()
pic.goto(72, 87)
pic.pendown()
pic.fillcolor(color)
pic.begin_fill()
pic.goto(96, 87)
pic.goto(84, 75)
pic.goto(72, 87)
pic.end_fill()

# 第四层三角形
pic.penup()
pic.goto(76, 75)
pic.pendown()
pic.fillcolor(color)
pic.begin_fill()
pic.goto(92, 75)
pic.goto(84, 63)
pic.goto(76, 75)
pic.end_fill()

# 第五层三角形（顶部）
pic.penup()
pic.goto(80, 63)
pic.pendown()
pic.fillcolor(color)
pic.begin_fill()
pic.goto(88, 63)
pic.goto(84, 57)
pic.goto(80, 63)
pic.end_fill()

# 绘制棕色树干
display.fill_rect(20, 230, 8, 10, st7789.color565(173, 135, 107))

'''绘制圣诞树（多层三角形，整体左移180）'''
color = st7789.color565(0, 255, 0)  # 绿色圣诞树
pic.pencolor(color)
# 第一层三角形（底部）
pic.penup()
pic.goto(-116, 109)
pic.pendown()
pic.fillcolor(color)
pic.begin_fill()
pic.goto(-76, 109)
pic.goto(-96, 99)
pic.goto(-116, 109)
pic.end_fill()

# 第二层三角形
pic.penup()
pic.goto(-112, 99)
pic.pendown()
pic.begin_fill()
pic.goto(-80, 99)
pic.goto(-96, 88)
pic.goto(-112, 99)
pic.end_fill()

# 第三层三角形
pic.penup()
pic.goto(-108, 87)
pic.pendown()
pic.begin_fill()
pic.goto(-84, 87)
pic.goto(-96, 75)
pic.goto(-108, 87)
pic.end_fill()

# 第四层三角形
pic.penup()
pic.goto(-104, 75)
pic.pendown()
pic.begin_fill()
pic.goto(-88, 75)
pic.goto(-96, 63)
pic.goto(-104, 75)
pic.end_fill()

# 第五层三角形（顶部）
pic.penup()
pic.goto(-100, 63)
pic.pendown()
pic.begin_fill()
pic.goto(-92, 63)
pic.goto(-96, 57)
pic.goto(-100, 63)
pic.end_fill()

# 画蓝色圆
display.fill_circle(120, 130, 80, st7789.color565(0, 240, 245))

# 初始化 IMU / RTC
imu = icm20948.ICM20948(I2C(0), gyro_scale=icm20948.DPS_2000)
i2c = I2C(1, sda=Pin(0), scl=Pin(1), freq=400000)
ds = ds1307.DS1307(i2c)
KEY_PIN = 13
key = Pin(13)
key.init(Pin.IN)
key.pull(Pin.PULL_DOWN)
weeklist = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']

# ==================== 2. 新增：运行状态变量 ====================
running = False  # False=Stopped，True=Running
in_summary_screen = False  # 新增：是否在总结页面
last_key_val = 1  # 上一次电平，用于边缘检测
# =============================================================

# 原有计步/配速变量
threshold_min, threshold_max = 700, 1400
steps = 0
last_step_time = 0
is_moving = False
start_time = 0
last_pace_update = utime.ticks_ms()
# ---------- 高精度配速 ----------
PACE_UPDATE_MS = 500  # 0.5 s 刷新
ALPHA_EMA = 0.3  # 指数平均系数，越小越平滑
pace_ema = 0  # 平滑后的秒/步
step_buf = []  # 最近 20 步的时间戳
DIST_PER_STEP = 0.7  # 初始步幅（m）
# 移除IRQ处理，使用轮询方式
key_pin.irq(handler=None)

# 新增：用于计算平均配速的变量
total_pace_sum = 0
total_pace_count = 0


def update_pace():
    global pace_ema, step_buf, DIST_PER_STEP, total_pace_sum, total_pace_count
    if len(step_buf) < 2:
        return 0
    # 1. 实时步幅校准（每 20 步更新一次）
    if len(step_buf) >= 20:
        DIST_PER_STEP = (utime.ticks_diff(step_buf[-1], step_buf[-20]) / 1000 * 1.2) / 19
        step_buf = step_buf[-20:]  # 保留最新 20 个
    # 2. 最近 5 步的平均步频 → 秒/步
    recent_5_ms = utime.ticks_diff(step_buf[-1], step_buf[-5]) if len(step_buf) >= 5 else \
        utime.ticks_diff(step_buf[-1], step_buf[0])
    pace_sec_per_step = recent_5_ms / 1000 / min(len(step_buf) - 1, 5)
    # 3. 指数平均平滑
    if pace_ema == 0:
        pace_ema = pace_sec_per_step
    else:
        pace_ema = ALPHA_EMA * pace_sec_per_step + (1 - ALPHA_EMA) * pace_ema
    # 4. 计算 min/km 并添加到总和中
    pace_min_per_km = pace_ema * 1000 / DIST_PER_STEP / 60
    total_pace_sum += pace_min_per_km
    total_pace_count += 1
    return pace_min_per_km


# ====== 旧值缓存，解决闪烁 ======
old_steps = -1
old_pace = (-1, -1)  # (分钟, 秒)
old_time = (-1, -1, -1, -1)  # (时, 分, 秒, 星期)
# =================================

# 新增：运动开始时间
workout_start_time = 0


# 新增：重新绘制主界面函数
def draw_main_interface():
    # 这里需要重新绘制你的主界面元素
    # 由于你的界面绘制代码比较复杂，我建议将其提取到一个函数中
    # 这里只是一个示例，你需要根据实际情况修改
    display.fill(0)
    # 重新绘制标题栏
    display.fill_rect(0, 0, 240, 40, st7789.color565(255, 105, 180))
    # 重新绘制其他界面元素...


while True:
    try:
        # =============== 3. 新增：按键扫描（边缘触发） ===============
        key_now = key.value()
        if key_now == 0 and last_key_val == 1:  # 下降沿
            if in_summary_screen:
                # 从总结页面返回主界面
                in_summary_screen = False
                display.fill(0)
                # 重新绘制主界面
                draw_main_interface()
                print(">>> Returned to main screen")
            elif not running:  # 开始运动
                running = True
                workout_start_time = utime.time()  # 记录开始时间
                steps = 0  # 重置步数
                total_pace_sum = 0  # 重置配速总和
                total_pace_count = 0  # 重置配速计数
                step_buf = []  # 清空步数缓冲区
                print(">>> Workout started")
            else:  # 结束运动
                running = False
                is_moving = False  # 结束运动时立刻置标志
                workout_duration = utime.time() - workout_start_time  # 计算运动时长

                # 计算平均配速
                avg_pace = total_pace_sum / total_pace_count if total_pace_count > 0 else 0

                # 显示结束页面
                in_summary_screen = True
                show_end_screen(steps, workout_duration, avg_pace)

                print(">>> Workout ended. Steps:", steps, "Duration:", workout_duration, "Avg Pace:", avg_pace)

        last_key_val = key_now
        # ============================================================

        # 如果在总结页面，只更新时间显示，不进行计步
        if in_summary_screen:
            current = ds.get_time()
            if len(current) >= 7:
                year, month, day, weekday, hour, minute, second = current[0:7]
            else:
                year, month, day, hour, minute, second = 2023, 1, 1, 0, 0, 0
                weekday = 0

            # 更新时间显示
            new_time = (hour, minute, second, weekday)
            if new_time != old_time:
                old_time = new_time
                # 更新时间显示区域
                display.fill_rect(0, 0, 240, 40, st7789.color565(255, 105, 180))
                display.draw_string(5, 10, "%04d" % year, size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(0, 240, 245))
                display.draw_string(55, 10, "%02d" % month, size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(180, 210, 180))
                display.draw_string(80, 10, "/", size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(180, 210, 180))
                display.draw_string(93, 10, "%02d" % day, size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(180, 210, 180))
                display.draw_string(120, 10, "%02d" % hour, size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 105, 180))
                display.draw_string(127, 10, ":", size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 105, 180))
                display.draw_string(136, 10, "%02d" % minute, size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 105, 180))
                display.draw_string(159, 10, ":", size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 105, 180))
                display.draw_string(170, 10, "%02d" % second, size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 105, 180))
                if weekday < len(weeklist):
                    display.draw_string(198, 10, "%s" % weeklist[weekday], size=2, color=st7789.color565(255, 255, 255),
                                        bg=st7789.color565(255, 235, 100))
                else:
                    display.draw_string(198, 10, "---", size=2, color=st7789.color565(255, 255, 255),
                                        bg=st7789.color565(255, 235, 100))
            utime.sleep(0.1)
            continue  # 跳过后续的计步逻辑

        # 正常主界面逻辑
        current = ds.get_time()
        if len(current) >= 7:
            year, month, day, weekday, hour, minute, second = current[0:7]
        else:
            year, month, day, hour, minute, second = 2023, 1, 1, 0, 0, 0
            weekday = 0
        # 只有"时分秒或星期"变化才重画
        new_time = (hour, minute, second, weekday)
        if new_time != old_time:
            old_time = new_time
            # 下面整段就是你原来画时间条的代码，一字符不动
            display.draw_string(5, 10, "%04d" % year, size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(0, 240, 245))
            display.draw_string(55, 10, "%02d" % month, size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(180, 210, 180))
            display.draw_string(80, 10, "/", size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(180, 210, 180))
            display.draw_string(93, 10, "%02d" % day, size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(180, 210, 180))
            display.draw_string(120, 10, "%02d" % hour, size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(255, 105, 180))
            display.draw_string(127, 10, ":", size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(255, 105, 180))
            display.draw_string(136, 10, "%02d" % minute, size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(255, 105, 180))
            display.draw_string(159, 10, ":", size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(255, 105, 180))
            display.draw_string(170, 10, "%02d" % second, size=2, color=st7789.color565(255, 255, 255),
                                bg=st7789.color565(255, 105, 180))
            if weekday < len(weeklist):
                display.draw_string(198, 10, "%s" % weeklist[weekday], size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 235, 100))
            else:
                display.draw_string(198, 10, "---", size=2, color=st7789.color565(255, 255, 255),
                                    bg=st7789.color565(255, 235, 100))
        '''================  计步模块（10 s 刷新配速）  ================'''

        # =============== 4. 新增：只有 running==True 才采 IMU ===============
        if running:
            imu.dataupdate()
            xacc, yacc, zacc = imu.acc_x(), imu.acc_y(), imu.acc_z()
            totave = math.sqrt(xacc * xacc + yacc * yacc + zacc * zacc)
            current_time_sec = utime.time()
            # 步数检测（0.3 s 去抖）
            if (totave < threshold_min or totave > threshold_max) and \
                    (current_time_sec - last_step_time > 0.3):
                steps += 1
                last_step_time = current_time_sec
                if steps == 1:
                    start_time = current_time_sec
                    is_moving = True
        if steps != old_steps:
            old_steps = steps
            display.fill_rect(60, 100, 130, 20, st7789.color565(0, 0, 0))  # 只清这一行
            display.draw_string(60, 100, "Steps:%d" % steps, size=2,
                                color=st7789.color565(255, 255, 255))
        # 配速区
        if running and steps > 0:
            step_buf.append(utime.ticks_ms())
            if utime.ticks_diff(utime.ticks_ms(), last_pace_update) >= PACE_UPDATE_MS:
                pace_min_per_km = update_pace()
                last_pace_update = utime.ticks_ms()
        else:
            pace_min_per_km = 0

        if pace_min_per_km > 0:
            minutes = int(pace_min_per_km)
            seconds = int((pace_min_per_km - minutes) * 60)
            new_pace = (minutes, seconds)
        else:
            new_pace = (-1, -1)  # 代表 "--:--"
        if new_pace != old_pace:
            old_pace = new_pace
            display.fill_rect(60, 130, 130, 20, st7789.color565(0, 0, 0))  # 只清这一行
            if pace_min_per_km > 0:
                display.draw_string(60, 130, "Pace:%d:%02d" % (minutes, seconds),
                                    size=2, color=st7789.color565(255, 255, 255))
            else:
                display.draw_string(60, 130, "Pace:--:--", size=2,
                                    color=st7789.color565(255, 255, 255))
        # 给一个小图标提示当前状态
        display.fill_circle(220, 60, 6,
                            st7789.color565(0, 255, 0) if running else st7789.color565(255, 0, 0))

    except Exception as e:
        print("Error:", e)
        display.draw_string(80, 100, "Error occurred", size=2, color=st7789.color565(255, 0, 0))
    utime.sleep(0.1)